package com.example.myinput;

import android.os.SystemClock;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.graphics.PointF;

import org.json.JSONObject;

import java.util.List;

public class Touch {
    private static final String MOUSE_DOWN = "mousedown";
    private static final String MOUSE_UP = "mouseup";
    private static final String MOUSE_MOVE = "mousemove";
    public static int getAction(String eventName){
        switch (eventName){
            case MOUSE_DOWN:
                return MotionEvent.ACTION_DOWN;
            case MOUSE_UP:
                return MotionEvent.ACTION_UP;
            case MOUSE_MOVE:
                return MotionEvent.ACTION_MOVE;
        }
        return -1;
    }

    public static boolean touchCheck(String... args){
        if(args.length!=4){
            System.out.println("args less");
            return false;
        }
        String eventName=args[1];
        float x=Float.parseFloat(args[2]);
        float y=Float.parseFloat(args[3]);
        return touchCheck(eventName,x,y);
    }
    public static boolean touchCheck(String eventName,float x,float y){
        int action=getAction(eventName);
        if(action<0){
            System.out.println("event error");
            return false;
        }
        if(x<0){
            System.out.println("x error");
            return false;
        }
        if(y<0){
            System.out.println("y error");
            return false;
        }
        return true;
    }

    public static boolean touchCheck(int x,int y,int nums,int durationMs){
        if(x<0){
            System.out.println("x error");
            return false;
        }
        if(y<0){
            System.out.println("y error");
            return false;
        }
        if(nums<0){
            System.out.println("nums error");
            return false;
        }
        if(durationMs<0){
            System.out.println("durationMs error");
            return false;
        }
        return true;
    }

    //单点滑动
    //--Touch mousedown 100 200  --Touch mousemove 110 200 --Touch mousemove 120 200 --Touch mouseup 140 200
    public static boolean touch(String... args){
        String eventName=args[1];
        float x=Float.parseFloat(args[2]);
        float y=Float.parseFloat(args[3]);
        return touch(eventName,x,y);
    }
    public static boolean touch(String eventName,float x,float y){
        try{
            int action=getAction(eventName);
            long downTime=getTime("downTime");
            long eventTime=getTime("eventTime");   //和鼠标按下点的时间差值，单位毫秒
            if(eventName=="mousedown") {
                downTime = SystemClock.uptimeMillis();
                eventTime = downTime;
                writeTime(downTime,eventTime);
            }
            if(eventTime<SystemClock.uptimeMillis()){
                eventTime=SystemClock.uptimeMillis();
            }
            eventTime += 10;
            System.out.println("action:"+eventName+",eventTime:"+eventTime+",x:"+x+",y:"+y);
            MotionEvent touchEvent =MotionEvent.obtain(downTime,eventTime,action,x,y,0);
            touchEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
            InputManger.getInstance().injectInputEvent(touchEvent,0);
            touchEvent.recycle();
            writeEventTime(eventTime);
            System.out.println("event success");
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    public static boolean checkSwipe(String... args){
        if(args.length!=6){
            System.out.println("args less");
            return false;
        }
        float x1=Float.parseFloat(args[1]);
        float y1=Float.parseFloat(args[2]);
        float x2=Float.parseFloat(args[3]);
        float y2=Float.parseFloat(args[4]);
        long durationMs=Long.parseLong(args[5]);
        return checkSwipe(x1,y1,x2,y2,durationMs);
    }
    public static boolean checkSwipe(float x1,float y1,float x2,float y2,long durationMs){
        if(x1<0){
            System.out.println("x1 error");
            return false;
        }
        if(y1<0){
            System.out.println("y1 error");
            return false;
        }
        if(x2<0){
            System.out.println("x2 error");
            return false;
        }
        if(y2<0){
            System.out.println("y2 error");
            return false;
        }
        if(durationMs<0){
            System.out.println("durationMs error");
            return false;
        }
        return true;
    }
    public static boolean swipeBezier(String... args){
        float x1=Float.parseFloat(args[1]);
        float y1=Float.parseFloat(args[2]);
        float x2=Float.parseFloat(args[3]);
        float y2=Float.parseFloat(args[4]);
        long durationMs=Long.parseLong(args[5]);
        return swipeBezier(x1,y1,x2,y2,durationMs);
    }

    public static boolean swipeBezier(float x1,float y1,float x2,float y2,long durationMs){
        try {
            long downTime = SystemClock.uptimeMillis();
            long eventTime = downTime;
            MotionEvent touchEvent = MotionEvent.obtain(
                    downTime,
                    eventTime,
                    MotionEvent.ACTION_DOWN,
                    x1,
                    y1,
                    0
            );
            touchEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
            InputManger.getInstance().injectInputEvent(touchEvent,0);
            touchEvent.recycle();
            List<PointF> points=BezierUtil.randomPoints(x1,y1,x2,y2,100,10f,5f);
            for (int i = 0; i < points.size(); i++) {
                eventTime += durationMs / points.size();
                System.out.println("x:"+points.get(i).x+",y:"+points.get(i).y+",eventTime:"+eventTime);
                MotionEvent moveEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_MOVE,
                        points.get(i).x,
                        points.get(i).y,
                        0
                );
                moveEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(moveEvent, 0);
                moveEvent.recycle();
                SystemClock.sleep(durationMs / points.size()); // 模拟自然滑动
            }

            // ACTION_UP
            eventTime += 10;
            MotionEvent upEvent = MotionEvent.obtain(
                    downTime,
                    eventTime,
                    MotionEvent.ACTION_UP,
                    x2,
                    y2,
                    0
            );
            upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
            InputManger.getInstance().injectInputEvent(upEvent, 0);
            upEvent.recycle();
            System.out.println("swipe2 success");
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    //完整滑动
    public static boolean swipe(String... args){
        float x1=Float.parseFloat(args[1]);
        float y1=Float.parseFloat(args[2]);
        float x2=Float.parseFloat(args[3]);
        float y2=Float.parseFloat(args[4]);
        long durationMs=Long.parseLong(args[5]);
        return swipe(x1,y1,x2,y2,durationMs);
    }


    public static boolean swipe(float x1,float y1,float x2,float y2,long durationMs){
        try {
            long downTime = SystemClock.uptimeMillis();
            long eventTime = downTime;
            int steps = 20;
            float stepX =Math.abs(x1-x2) / (float) steps;
            float stepY =Math.abs(y1-y2) / (float) steps;
            System.out.println("x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2+",durationMs:"+durationMs+",stepX:"+stepX+",stepY:"+stepY+",y1-y2:"+(y1-y2));
            MotionEvent touchEvent = MotionEvent.obtain(
                    downTime,
                    eventTime,
                    MotionEvent.ACTION_DOWN,
                    x1,
                    y1,
                    0
            );
            touchEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
            InputManger.getInstance().injectInputEvent(touchEvent,0);
            touchEvent.recycle();
            for (int i = 1; i <= steps; i++) {
                eventTime += durationMs / steps;
                float x = x1 + stepX * i;
                if(x1>x2){
                    x = x1 - stepX * i;
                }
                float y = y1 + stepY * i;
                if(y1>y2){
                    y = y1 - stepY * i;
                }
                System.out.println("x:"+x+",y:"+y+",eventTime:"+eventTime);
                MotionEvent moveEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_MOVE,
                        x,
                        y,
                        0
                );
                moveEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(moveEvent, 0);
                moveEvent.recycle();
                SystemClock.sleep(durationMs / steps); // 模拟自然滑动
            }

            // ACTION_UP
            eventTime += 10;
            MotionEvent upEvent = MotionEvent.obtain(
                    downTime,
                    eventTime,
                    MotionEvent.ACTION_UP,
                    x2,
                    y2,
                    0
            );
            upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
            InputManger.getInstance().injectInputEvent(upEvent, 0);
            upEvent.recycle();
            System.out.println("swipe success");
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    public static boolean checkFenDuan(String... args){
        if(args.length!=11){
            System.out.println("args less");
            return false;
        }
        float x1=Float.parseFloat(args[1]);
        float y1=Float.parseFloat(args[2]);
        float x2=Float.parseFloat(args[3]);
        float y2=Float.parseFloat(args[4]);
        int nums=Integer.parseInt(args[5]);
        float mLeaveHeightLength=Float.parseFloat(args[6]);
        float mh=Float.parseFloat(args[7]);
        long durationMs=Long.parseLong(args[8]);
        int willContinue=Integer.parseInt(args[9]);
        return checkFenDuan(x1,y1,x2,y2,nums,mLeaveHeightLength,mh,durationMs,willContinue);
    }
    public static boolean checkFenDuan(float x1,float y1,float x2,float y2,int nums,float mLeaveHeightLength,float mh,long durationMs,int willContinue){
        if(x1<0){
            System.out.println("x1 error");
            return false;
        }
        if(y1<0){
            System.out.println("y1 error");
            return false;
        }
        if(x2<0){
            System.out.println("x2 error");
            return false;
        }
        if(y2<0){
            System.out.println("y2 error");
            return false;
        }
        if(nums<0){
            System.out.println("nums error");
            return false;
        }
        if(mLeaveHeightLength<0){
            System.out.println("mLeaveHeightLength error");
            return false;
        }
        if(mh<0){
            System.out.println("mh error");
            return false;
        }
        if(durationMs<0){
            System.out.println("durationMs error");
            return false;
        }
        if(willContinue<0&&willContinue>3){
            System.out.println("willContinue error");
            return false;
        }
        return true;
    }
    public static boolean checkFenDuan(int x1,int y1,int x2,int y2,int nums,int mLeaveHeightLength,int mh,int durationMs,int willContinue){
        if(x1<0){
            System.out.println("x1 error");
            return false;
        }
        if(y1<0){
            System.out.println("y1 error");
            return false;
        }
        if(x2<0){
            System.out.println("x2 error");
            return false;
        }
        if(y2<0){
            System.out.println("y2 error");
            return false;
        }
        if(nums<0){
            System.out.println("nums error");
            return false;
        }
        if(mLeaveHeightLength<0){
            System.out.println("mLeaveHeightLength error");
            return false;
        }
        if(mh<0){
            System.out.println("mh error");
            return false;
        }
        if(durationMs<0){
            System.out.println("durationMs error");
            return false;
        }
        if(willContinue<0&&willContinue>3){
            System.out.println("willContinue error");
            return false;
        }
        return true;
    }
    public static boolean writeTime(long downTime,long eventTime){
        try {
            JSONObject clock=new JSONObject();
            clock.put("downTime",downTime);
            clock.put("eventTime",eventTime);
            FileOp.writeJson("/data/local/tmp/input.json",clock);
            return true;
        }catch (Exception e){
        }
        return false;
    }
    public static boolean writeEventTime(long eventTime){
        try {
            JSONObject js=FileOp.readJson("/data/local/tmp/input.json");
            js.put("eventTime",eventTime);
            FileOp.writeJson("/data/local/tmp/input.json",js);
            return true;
        }catch (Exception e){
        }
        return false;
    }
    public static long getTime(String key){
        try {
            JSONObject js=FileOp.readJson("/data/local/tmp/input.json");
            if(js!=null&&js.has(key)){
                return js.getLong(key);
            }
        }catch (Exception e){
        }
        return SystemClock.uptimeMillis();
    }
    //willContinue: 0 MOUSE_DOWN  1 MOUSE_MOVE 2MOUSE_DOWN 3 MOUSE_DOWN && 2MOUSE_DOWN
    public static boolean fenDuan(String... args){
        float x1=Float.parseFloat(args[1]);
        float y1=Float.parseFloat(args[2]);
        float x2=Float.parseFloat(args[3]);
        float y2=Float.parseFloat(args[4]);
        int nums=Integer.parseInt(args[5]);
        float mLeaveHeightLength=Float.parseFloat(args[6]);
        float mh=Float.parseFloat(args[7]);
        long durationMs=Long.parseLong(args[8]);
        int willContinue=Integer.parseInt(args[9]);
        float pressure=Float.parseFloat(args[10]);
        return fenDuan(x1,y1,x2,y2,nums,mLeaveHeightLength,mh,durationMs,willContinue,pressure);
    }


    public static boolean fenDuan(float x1,float y1,float x2,float y2,int nums,float mLeaveHeightLength,float mh,long durationMs,int willContinue,float pressure){
        try {
            long downTime = getTime("downTime");
            long eventTime = getTime("eventTime");
            if(willContinue==0||willContinue==3){
                downTime=SystemClock.uptimeMillis();
                eventTime=downTime;
                MotionEvent touchEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_DOWN,
                        x1,
                        y1,
                        pressure,
                        1.0f,
                        0,
                        1.0f, 1.0f,      // precision
                        0,               // deviceId
                        0
                );
                touchEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(touchEvent,0);
                touchEvent.recycle();
                writeTime(downTime,eventTime);
                System.out.println("mouse down");
            }
            List<PointF> points=BezierUtil.randomPoints(x1,y1,x2,y2,nums,mLeaveHeightLength,mh);
            if(eventTime<SystemClock.uptimeMillis()){
                eventTime=SystemClock.uptimeMillis();
            }
            for (int i = 0; i < points.size(); i++) {
                eventTime += durationMs / points.size();
                System.out.println("x:"+points.get(i).x+",y:"+points.get(i).y+",eventTime:"+eventTime+",willContinue:"+willContinue+",nums:"+nums+",mLeaveHeightLength:"+mLeaveHeightLength+",mh:"+mh+",pressure:"+pressure);
                MotionEvent moveEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_MOVE,
                        points.get(i).x,
                        points.get(i).y,
                        pressure,
                        1.0f,
                        0,
                        1.0f, 1.0f,      // precision
                        0,               // deviceId
                        0
                );
                moveEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(moveEvent, 0);
                moveEvent.recycle();
                SystemClock.sleep(durationMs / points.size());
            }
            writeEventTime(eventTime);
            if(willContinue==2||willContinue==3){
                // ACTION_UP
                eventTime += 10;
                MotionEvent upEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_UP,
                        x2,
                        y2,
                        pressure,
                        1.0f,
                        0,
                        1.0f, 1.0f,      // precision
                        0,               // deviceId
                        0
                );
                upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(upEvent, 0);
                upEvent.recycle();
                writeEventTime(eventTime);
                System.out.println("mouse up");
            }
            System.out.println("Bezier success");
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }


    public static boolean checkFenDuanTrajectory(String... args){
        if(args.length!=9){
            System.out.println("args less");
            return false;
        }
        float x1=Float.parseFloat(args[1]);
        float y1=Float.parseFloat(args[2]);
        float x2=Float.parseFloat(args[3]);
        float y2=Float.parseFloat(args[4]);
        int nums=Integer.parseInt(args[5]);
        long durationMs=Long.parseLong(args[6]);
        int willContinue=Integer.parseInt(args[7]);
        return checkFenDuanTrajectory(x1,y1,x2,y2,nums,durationMs,willContinue);
    }

    public static boolean checkFenDuanTrajectory(float x1,float y1,float x2,float y2,int nums,long durationMs,int willContinue){
        if(x1<0){
            System.out.println("x1 error");
            return false;
        }
        if(y1<0){
            System.out.println("y1 error");
            return false;
        }
        if(x2<0){
            System.out.println("x2 error");
            return false;
        }
        if(y2<0){
            System.out.println("y2 error");
            return false;
        }
        if(nums<0){
            System.out.println("nums error");
            return false;
        }
        if(durationMs<0){
            System.out.println("durationMs error");
            return false;
        }
        if(willContinue<0&&willContinue>3){
            System.out.println("willContinue error");
            return false;
        }
        return true;
    }


    public static boolean checkFenDuanTrajectory(int x1,int y1,int x2,int y2,int nums,int durationMs,int willContinue){
        if(x1<0){
            System.out.println("x1 error");
            return false;
        }
        if(y1<0){
            System.out.println("y1 error");
            return false;
        }
        if(x2<0){
            System.out.println("x2 error");
            return false;
        }
        if(y2<0){
            System.out.println("y2 error");
            return false;
        }
        if(nums<0){
            System.out.println("nums error");
            return false;
        }
        if(durationMs<0){
            System.out.println("durationMs error");
            return false;
        }
        if(willContinue<0&&willContinue>3){
            System.out.println("willContinue error");
            return false;
        }
        return true;
    }

    //willContinue: 0 MOUSE_DOWN  1 MOUSE_MOVE 2MOUSE_DOWN 3 MOUSE_DOWN && 2MOUSE_DOWN
    public static boolean fenDuanTrajectory(String... args){
        float x1=Float.parseFloat(args[1]);
        float y1=Float.parseFloat(args[2]);
        float x2=Float.parseFloat(args[3]);
        float y2=Float.parseFloat(args[4]);
        int nums=Integer.parseInt(args[5]);
        long durationMs=Long.parseLong(args[6]);
        int willContinue=Integer.parseInt(args[7]);
        float pressure=Float.parseFloat(args[8]);
        return fenDuanTrajectory(x1,y1,x2,y2,nums,durationMs,willContinue,pressure);
    }


    public static boolean fenDuanTrajectory(float x1,float y1,float x2,float y2,int nums,long durationMs,int willContinue,float pressure){
        try {

            List<PointF> points=TrajectoryGenerator.randomPoints(x1,y1,x2,y2,nums);
            System.out.println("x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2+",nums:"+nums+",durationMs:"+durationMs+",willContinue:"+willContinue+",pressure:"+pressure);
            long downTime = getTime("downTime");
            long eventTime = getTime("eventTime");
            if(willContinue==0||willContinue==3){
                downTime=SystemClock.uptimeMillis();
                eventTime=downTime;
                MotionEvent touchEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_DOWN,
                        x1,
                        y1,
                        pressure,
                        1.0f,
                        0,
                        1.0f, 1.0f,      // precision
                        0,               // deviceId
                        0
                );
                touchEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(touchEvent,0);
                touchEvent.recycle();
                writeTime(downTime,eventTime);
                System.out.println("mouse down");
            }
            if(eventTime<SystemClock.uptimeMillis()){
                eventTime=SystemClock.uptimeMillis();
            }
            for (int i = 0; i < points.size(); i++) {
                eventTime += durationMs / points.size();
                System.out.println("x:"+points.get(i).x+",y:"+points.get(i).y+",eventTime:"+eventTime);
                MotionEvent moveEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_MOVE,
                        points.get(i).x,
                        points.get(i).y,
                        pressure,
                        1.0f,
                        0,
                        1.0f, 1.0f,      // precision
                        0,               // deviceId
                        0
                );
                moveEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(moveEvent, 0);
                moveEvent.recycle();
                SystemClock.sleep(durationMs / points.size());
            }
            writeEventTime(eventTime);
            if(willContinue==2||willContinue==3){
                // ACTION_UP
                eventTime += 10;
                MotionEvent upEvent = MotionEvent.obtain(
                        downTime,
                        eventTime,
                        MotionEvent.ACTION_UP,
                        x2,
                        y2,
                        pressure,
                        1.0f,
                        0,
                        1.0f, 1.0f,      // precision
                        0,               // deviceId
                        0
                );
                upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                InputManger.getInstance().injectInputEvent(upEvent, 0);
                upEvent.recycle();
                writeEventTime(eventTime);
                System.out.println("mouse up");
            }
            System.out.println("Trajectory success");
            return true;
        }catch (Exception e){

        }
        return false;
    }
    public static void touchStop(int x,int y,int num,int durationMs,int pressure,int isUp){
        InputManger.getInstance().injectStop(x,y,num,durationMs,pressure,isUp);
    }
    public static void injectBezier(int x1,int y1,int x2,int y2,int num,int mLeaveHeightLength,int mh,int durationMs,int willContinue,int pressure){
        InputManger.getInstance().injectBezier(x1,y1,x2,y2,num,mLeaveHeightLength,mh,durationMs,willContinue,pressure);
    }

    public static void injectTrajectory(int x1,int y1,int x2,int y2,int num,int durationMs,int willContinue,int pressure){
        InputManger.getInstance().injectTrajectory(x1,y1,x2,y2,num,durationMs,willContinue,pressure);
    }
}
